From: kaf24@firebug.cl.cam.ac.uk Date: Thu, 29 Sep 2005 14:14:03 +0000 (+0100) Subject: Change semantics of bind_evtchn_to_xxx and X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16769^2~11 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=eb3abaa7a237c5df141f7ad82831f0a1bc9d43fb;p=xen.git Change semantics of bind_evtchn_to_xxx and unbind_evtchn_from_xxx. The bind now returns the IRQ number on success. The unbind takes this as a parameter instead of the event-channel port. Also, unbind closes down the underlying event-channel port if it is still live. Signed-off-by: Keir Fraser --- diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c index 1f94775476..32294c7bcd 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c @@ -320,13 +320,19 @@ int bind_evtchn_to_irq(unsigned int evtchn) } EXPORT_SYMBOL(bind_evtchn_to_irq); -void unbind_evtchn_from_irq(unsigned int evtchn) +void unbind_evtchn_from_irq(unsigned int irq) { - int irq = evtchn_to_irq[evtchn]; + evtchn_op_t op; + int evtchn = irq_to_evtchn[irq]; spin_lock(&irq_mapping_update_lock); - if (--irq_bindcount[irq] == 0) { + if ((--irq_bindcount[irq] == 0) && (evtchn != -1)) { + op.cmd = EVTCHNOP_close; + op.u.close.dom = DOMID_SELF; + op.u.close.port = evtchn; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + evtchn_to_irq[evtchn] = -1; irq_to_evtchn[irq] = -1; } @@ -348,17 +354,16 @@ int bind_evtchn_to_irqhandler( irq = bind_evtchn_to_irq(evtchn); retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) - unbind_evtchn_from_irq(evtchn); + unbind_evtchn_from_irq(irq); - return retval; + return irq; } EXPORT_SYMBOL(bind_evtchn_to_irqhandler); -void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id) +void unbind_evtchn_from_irqhandler(unsigned int irq, void *dev_id) { - unsigned int irq = evtchn_to_irq[evtchn]; free_irq(irq, dev_id); - unbind_evtchn_from_irq(evtchn); + unbind_evtchn_from_irq(irq); } EXPORT_SYMBOL(unbind_evtchn_from_irqhandler); @@ -425,9 +430,8 @@ static unsigned int startup_dynirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - if (!VALID_EVTCHN(evtchn)) - return 0; - unmask_evtchn(evtchn); + if (VALID_EVTCHN(evtchn)) + unmask_evtchn(evtchn); return 0; } @@ -435,38 +439,41 @@ static void shutdown_dynirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - if (!VALID_EVTCHN(evtchn)) - return; - mask_evtchn(evtchn); + if (VALID_EVTCHN(evtchn)) + mask_evtchn(evtchn); } static void enable_dynirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - unmask_evtchn(evtchn); + if (VALID_EVTCHN(evtchn)) + unmask_evtchn(evtchn); } static void disable_dynirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - mask_evtchn(evtchn); + if (VALID_EVTCHN(evtchn)) + mask_evtchn(evtchn); } static void ack_dynirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - mask_evtchn(evtchn); - clear_evtchn(evtchn); + if (VALID_EVTCHN(evtchn)) { + mask_evtchn(evtchn); + clear_evtchn(evtchn); + } } static void end_dynirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - if (!(irq_desc[irq].status & IRQ_DISABLED)) + if (VALID_EVTCHN(evtchn) && !(irq_desc[irq].status & IRQ_DISABLED)) unmask_evtchn(evtchn); } @@ -559,35 +566,36 @@ static void shutdown_pirq(unsigned int irq) static void enable_pirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - if (!VALID_EVTCHN(evtchn)) - return; - unmask_evtchn(evtchn); - pirq_unmask_notify(irq_to_pirq(irq)); + + if (VALID_EVTCHN(evtchn)) { + unmask_evtchn(evtchn); + pirq_unmask_notify(irq_to_pirq(irq)); + } } static void disable_pirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - if (!VALID_EVTCHN(evtchn)) - return; - mask_evtchn(evtchn); + + if (VALID_EVTCHN(evtchn)) + mask_evtchn(evtchn); } static void ack_pirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - if (!VALID_EVTCHN(evtchn)) - return; - mask_evtchn(evtchn); - clear_evtchn(evtchn); + + if (VALID_EVTCHN(evtchn)) { + mask_evtchn(evtchn); + clear_evtchn(evtchn); + } } static void end_pirq(unsigned int irq) { int evtchn = irq_to_evtchn[irq]; - if (!VALID_EVTCHN(evtchn)) - return; - if (!(irq_desc[irq].status & IRQ_DISABLED)) { + + if (VALID_EVTCHN(evtchn) && !(irq_desc[irq].status & IRQ_DISABLED)) { unmask_evtchn(evtchn); pirq_unmask_notify(irq_to_pirq(irq)); } @@ -637,6 +645,10 @@ void irq_resume(void) BUG_ON(per_cpu(ipi_to_evtchn, cpu)[ipi] != -1); } + /* No IRQ -> event-channel mappings. */ + for (irq = 0; irq < NR_IRQS; irq++) + irq_to_evtchn[irq] = -1; + /* Primary CPU: rebind VIRQs automatically. */ for (virq = 0; virq < NR_VIRQS; virq++) { if ((irq = per_cpu(virq_to_irq, 0)[virq]) == -1) @@ -676,6 +688,13 @@ void irq_resume(void) /* Ready for use. */ unmask_evtchn(evtchn); } + + /* Remove defunct event-channel -> IRQ mappings. */ + for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) { + if ((evtchn_to_irq[evtchn] != -1) && + (irq_to_evtchn[evtchn_to_irq[evtchn]] == -1)) + evtchn_to_irq[evtchn] = -1; + } } void __init init_IRQ(void) @@ -689,11 +708,10 @@ void __init init_IRQ(void) init_evtchn_cpu_bindings(); + /* No VIRQ or IPI bindings. */ for (cpu = 0; cpu < NR_CPUS; cpu++) { - /* No VIRQ -> IRQ mappings. */ for (i = 0; i < NR_VIRQS; i++) per_cpu(virq_to_irq, cpu)[i] = -1; - /* No VIRQ -> IRQ mappings. */ for (i = 0; i < NR_IPIS; i++) per_cpu(ipi_to_evtchn, cpu)[i] = -1; } diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c index 03fff886aa..ab8f32e531 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @@ -65,12 +65,6 @@ static int __do_suspend(void *ignore) { int i, j, k, fpp; -#ifdef CONFIG_XEN_USB_FRONTEND - extern void usbif_resume(); -#else -#define usbif_resume() do{}while(0) -#endif - extern int gnttab_suspend(void); extern int gnttab_resume(void); @@ -87,7 +81,6 @@ static int __do_suspend(void *ignore) int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); #endif - extern void xencons_suspend(void); extern void xencons_resume(void); int err = 0; @@ -147,17 +140,15 @@ static int __do_suspend(void *ignore) } #endif + xenbus_suspend(); + + gnttab_suspend(); + #ifdef __i386__ mm_pin_all(); kmem_cache_shrink(pgd_cache); #endif - xenbus_suspend(); - - xencons_suspend(); - - gnttab_suspend(); - HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; clear_fixmap(FIX_SHARED_INFO); @@ -202,8 +193,6 @@ static int __do_suspend(void *ignore) time_resume(); - usbif_resume(); - #ifdef CONFIG_SMP for_each_cpu_mask(i, prev_present_cpus) restore_vcpu_context(i, &suspended_cpu_records[i]); diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h index ffc168d0a0..4235d3f4fe 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -44,7 +44,7 @@ typedef struct blkif_st { unsigned int handle; /* Physical parameters of the comms window. */ unsigned int evtchn; - unsigned int remote_evtchn; + unsigned int irq; /* Comms information. */ blkif_back_ring_t blk_ring; struct vm_struct *blk_ring_area; diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c index 15649685d5..92e37850b3 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c @@ -71,8 +71,6 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain }; int err; - BUG_ON(blkif->remote_evtchn); - if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL ) return -ENOMEM; @@ -94,13 +92,12 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) } blkif->evtchn = op.u.bind_interdomain.port1; - blkif->remote_evtchn = evtchn; sring = (blkif_sring_t *)blkif->blk_ring_area->addr; SHARED_RING_INIT(sring); BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); - bind_evtchn_to_irqhandler( + blkif->irq = bind_evtchn_to_irqhandler( blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); blkif->status = CONNECTED; @@ -109,21 +106,13 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) static void free_blkif(void *arg) { - evtchn_op_t op = { .cmd = EVTCHNOP_close }; blkif_t *blkif = (blkif_t *)arg; - op.u.close.port = blkif->evtchn; - op.u.close.dom = DOMID_SELF; - HYPERVISOR_event_channel_op(&op); - op.u.close.port = blkif->remote_evtchn; - op.u.close.dom = blkif->domid; - HYPERVISOR_event_channel_op(&op); + if (blkif->irq) + unbind_evtchn_from_irqhandler(blkif->irq, blkif); vbd_free(&blkif->vbd); - if (blkif->evtchn) - unbind_evtchn_from_irqhandler(blkif->evtchn, blkif); - if (blkif->blk_ring.sring) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 8c1db775ff..209cd6b101 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -357,8 +357,9 @@ static void blkif_free(struct blkfront_info *info) if (info->ring_ref != GRANT_INVALID_REF) gnttab_end_foreign_access(info->ring_ref, 0); info->ring_ref = GRANT_INVALID_REF; - unbind_evtchn_from_irqhandler(info->evtchn, info); - info->evtchn = 0; + if (info->irq) + unbind_evtchn_from_irqhandler(info->irq, info); + info->evtchn = info->irq = 0; } static void blkif_recover(struct blkfront_info *info) @@ -429,10 +430,12 @@ static void blkif_connect(struct blkfront_info *info, u16 evtchn) err = bind_evtchn_to_irqhandler( info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info); - if (err != 0) { + if (err <= 0) { WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); return; } + + info->irq = err; } diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h index 9dc7a54379..24388e84e5 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h @@ -123,7 +123,7 @@ struct blkfront_info int backend_id; int ring_ref; blkif_front_ring_t ring; - unsigned int evtchn; + unsigned int evtchn, irq; struct xlbd_major_info *mi; request_queue_t *rq; struct work_struct work; diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h index 3caae4654f..38fa80b557 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h @@ -46,7 +46,7 @@ typedef struct blkif_st { unsigned int handle; /* Physical parameters of the comms window. */ unsigned int evtchn; - unsigned int remote_evtchn; + unsigned int irq; /* Comms information. */ blkif_back_ring_t blk_ring; struct vm_struct *blk_ring_area; diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c index 7719b76acc..85cf5d7362 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c @@ -71,8 +71,6 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain }; int err; - BUG_ON(blkif->remote_evtchn); - if ((blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL) return -ENOMEM; @@ -93,35 +91,26 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) return err; } - blkif->evtchn = op.u.bind_interdomain.port1; - blkif->remote_evtchn = evtchn; sring = (blkif_sring_t *)blkif->blk_ring_area->addr; SHARED_RING_INIT(sring); BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); - bind_evtchn_to_irqhandler( + blkif->irq = bind_evtchn_to_irqhandler( blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); - blkif->status = CONNECTED; + + blkif->status = CONNECTED; return 0; } static void free_blkif(void *arg) { - evtchn_op_t op = { .cmd = EVTCHNOP_close }; blkif_t *blkif = (blkif_t *)arg; - op.u.close.port = blkif->evtchn; - op.u.close.dom = DOMID_SELF; - HYPERVISOR_event_channel_op(&op); - op.u.close.port = blkif->remote_evtchn; - op.u.close.dom = blkif->domid; - HYPERVISOR_event_channel_op(&op); - - if (blkif->evtchn) - unbind_evtchn_from_irqhandler(blkif->evtchn, blkif); + if (blkif->irq) + unbind_evtchn_from_irqhandler(blkif->irq, blkif); if (blkif->blk_ring.sring) { unmap_frontend_page(blkif); diff --git a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c index 40d4da5349..2402a76ea4 100644 --- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c +++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c @@ -21,7 +21,6 @@ #include #include "xencons_ring.h" - struct ring_head { u32 cons; @@ -29,6 +28,7 @@ struct ring_head char buf[0]; } __attribute__((packed)); +static int xencons_irq; #define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head)) #define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE) @@ -97,32 +97,28 @@ int xencons_ring_init(void) { int err; + if (xencons_irq) + unbind_evtchn_from_irqhandler(xencons_irq, inring()); + xencons_irq = 0; + if (!xen_start_info->console_evtchn) return 0; - err = bind_evtchn_to_irqhandler(xen_start_info->console_evtchn, - handle_input, 0, "xencons", inring()); - if (err) { + err = bind_evtchn_to_irqhandler( + xen_start_info->console_evtchn, + handle_input, 0, "xencons", inring()); + if (err <= 0) { xprintk("XEN console request irq failed %i\n", err); return err; } - return 0; -} - -void xencons_suspend(void) -{ - - if (!xen_start_info->console_evtchn) - return; + xencons_irq = err; - unbind_evtchn_from_irqhandler(xen_start_info->console_evtchn, - inring()); + return 0; } void xencons_resume(void) { - (void)xencons_ring_init(); } diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/common.h b/linux-2.6-xen-sparse/drivers/xen/netback/common.h index 1c907cff9c..5150cb8844 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h @@ -50,7 +50,7 @@ typedef struct netif_st { u16 rx_shmem_handle; grant_ref_t rx_shmem_ref; unsigned int evtchn; - unsigned int remote_evtchn; + unsigned int irq; /* The shared rings and indexes. */ netif_tx_interface_t *tx; diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c index c3d525c3f4..b8b495ecb3 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c @@ -15,18 +15,17 @@ static void __netif_up(netif_t *netif) spin_lock_bh(&dev->xmit_lock); netif->active = 1; spin_unlock_bh(&dev->xmit_lock); - (void)bind_evtchn_to_irqhandler( - netif->evtchn, netif_be_int, 0, dev->name, netif); + enable_irq(netif->irq); netif_schedule_work(netif); } static void __netif_down(netif_t *netif) { struct net_device *dev = netif->dev; + disable_irq(netif->irq); spin_lock_bh(&dev->xmit_lock); netif->active = 0; spin_unlock_bh(&dev->xmit_lock); - unbind_evtchn_from_irqhandler(netif->evtchn, netif); netif_deschedule_work(netif); } @@ -203,7 +202,10 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref, } netif->evtchn = op.u.bind_interdomain.port1; - netif->remote_evtchn = evtchn; + + netif->irq = bind_evtchn_to_irqhandler( + netif->evtchn, netif_be_int, 0, netif->dev->name, netif); + disable_irq(netif->irq); netif->tx = (netif_tx_interface_t *)netif->comms_area->addr; netif->rx = (netif_rx_interface_t *) @@ -224,21 +226,15 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref, static void free_netif_callback(void *arg) { - evtchn_op_t op = { .cmd = EVTCHNOP_close }; netif_t *netif = (netif_t *)arg; /* - * These can't be done in netif_disconnect() because at that point + * This can't be done in netif_disconnect() because at that point * there may be outstanding requests in the network stack whose * asynchronous responses must still be notified to the remote driver. */ - - op.u.close.port = netif->evtchn; - op.u.close.dom = DOMID_SELF; - HYPERVISOR_event_channel_op(&op); - op.u.close.port = netif->remote_evtchn; - op.u.close.dom = netif->domid; - HYPERVISOR_event_channel_op(&op); + if (netif->irq) + unbind_evtchn_from_irqhandler(netif->irq, netif); unregister_netdev(netif->dev); diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 732e0d818e..abb4524dca 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -127,7 +127,7 @@ struct net_private spinlock_t rx_lock; unsigned int handle; - unsigned int evtchn; + unsigned int evtchn, irq; /* What is the status of our connection to the remote backend? */ #define BEST_CLOSED 0 @@ -815,7 +815,7 @@ connect_device(struct net_private *np, unsigned int evtchn) memcpy(dev->dev_addr, np->mac, ETH_ALEN); np->evtchn = evtchn; network_connect(dev); - (void)bind_evtchn_to_irqhandler( + np->irq = bind_evtchn_to_irqhandler( np->evtchn, netif_int, SA_SAMPLE_RANDOM, dev->name, dev); (void)send_fake_arp(dev); show_device(np); @@ -1055,8 +1055,9 @@ static void netif_free(struct netfront_info *info) gnttab_end_foreign_access(info->rx_ring_ref, 0); info->rx_ring_ref = GRANT_INVALID_REF; - unbind_evtchn_from_irqhandler(info->evtchn, info->netdev); - info->evtchn = 0; + if (info->irq) + unbind_evtchn_from_irqhandler(info->irq, info->netdev); + info->evtchn = info->irq = 0; } /* Stop network device and free tx/rx queues and irq. */ diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h index d447c873fa..25a1bbea25 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h @@ -35,7 +35,7 @@ typedef struct tpmif_st { /* Physical parameters of the comms window. */ unsigned int evtchn; - unsigned int remote_evtchn; + unsigned int irq; /* The shared rings and indexes. */ tpmif_tx_interface_t *tx; diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c index af93a6bdd4..43c6f6e0cc 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c @@ -120,8 +120,6 @@ tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn) evtchn_op_t op = {.cmd = EVTCHNOP_bind_interdomain }; int err; - BUG_ON(tpmif->remote_evtchn); - if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL) return -ENOMEM; @@ -143,12 +141,11 @@ tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn) } tpmif->evtchn = op.u.bind_interdomain.port1; - tpmif->remote_evtchn = evtchn; tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr; - bind_evtchn_to_irqhandler(tpmif->evtchn, - tpmif_be_int, 0, "tpmif-backend", tpmif); + tpmif->irq = bind_evtchn_to_irqhandler( + tpmif->evtchn, tpmif_be_int, 0, "tpmif-backend", tpmif); tpmif->status = CONNECTED; tpmif->shmem_ref = shared_page; tpmif->active = 1; @@ -159,18 +156,10 @@ tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn) static void __tpmif_disconnect_complete(void *arg) { - evtchn_op_t op = {.cmd = EVTCHNOP_close }; tpmif_t *tpmif = (tpmif_t *) arg; - op.u.close.port = tpmif->evtchn; - op.u.close.dom = DOMID_SELF; - HYPERVISOR_event_channel_op(&op); - op.u.close.port = tpmif->remote_evtchn; - op.u.close.dom = tpmif->domid; - HYPERVISOR_event_channel_op(&op); - - if (tpmif->evtchn) - unbind_evtchn_from_irqhandler(tpmif->evtchn, tpmif); + if (tpmif->irq) + unbind_evtchn_from_irqhandler(tpmif->irq, tpmif); if (tpmif->tx) { unmap_frontend_page(tpmif); diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index 0bd6114f43..516aae330d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -292,8 +292,10 @@ static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp) free_page((unsigned long)tp->tx); tp->tx = NULL; } - unbind_evtchn_from_irqhandler(tp->evtchn, NULL); - tp->evtchn = 0; + + if (tpm->irq) + unbind_evtchn_from_irqhandler(tp->irq, NULL); + tp->evtchn = tpm->irq = 0; } @@ -501,10 +503,12 @@ static void tpmif_connect(u16 evtchn, domid_t domid) err = bind_evtchn_to_irqhandler( tp->evtchn, tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp); - if ( err != 0 ) { + if ( err <= 0 ) { WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); return; } + + tp->irq = err; } static struct xenbus_device_id tpmfront_ids[] = { diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h index 9c7f51a2bc..f5ddea0cbf 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h @@ -5,7 +5,7 @@ struct tpm_private { tpmif_tx_interface_t *tx; - unsigned int evtchn; + unsigned int evtchn, irq; int connected; spinlock_t tx_lock; diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c index e0052d7f48..972236d285 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c @@ -44,6 +44,8 @@ struct ringbuf_head char buf[0]; } __attribute__((packed)); +static int xenbus_irq; + DECLARE_WAIT_QUEUE_HEAD(xb_waitq); static inline struct ringbuf_head *outbuf(void) @@ -205,33 +207,29 @@ int xb_init_comms(void) { int err; + if (xenbus_irq) + unbind_evtchn_from_irqhandler(xenbus_irq, &xb_waitq); + xenbus_irq = 0; + if (!xen_start_info->store_evtchn) return 0; err = bind_evtchn_to_irqhandler( xen_start_info->store_evtchn, wake_waiting, 0, "xenbus", &xb_waitq); - if (err) { + if (err <= 0) { printk(KERN_ERR "XENBUS request irq failed %i\n", err); - unbind_evtchn_from_irq(xen_start_info->store_evtchn); return err; } + xenbus_irq = err; + /* FIXME zero out page -- domain builder should probably do this*/ memset(mfn_to_virt(xen_start_info->store_mfn), 0, PAGE_SIZE); return 0; } -void xb_suspend_comms(void) -{ - - if (!xen_start_info->store_evtchn) - return; - - unbind_evtchn_from_irqhandler(xen_start_info->store_evtchn, &xb_waitq); -} - /* * Local variables: * c-file-style: "linux" diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h index 04500f4855..59ca0d3080 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h @@ -30,7 +30,6 @@ int xs_init(void); int xb_init_comms(void); -void xb_suspend_comms(void); /* Low level routines. */ int xb_write(const void *data, unsigned len); diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index 094d81870e..1ac3f457bc 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -607,7 +607,6 @@ void xenbus_suspend(void) down(&xenbus_lock); bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev); - xb_suspend_comms(); } void xenbus_resume(void) diff --git a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h index d364b0a4b5..360388fec6 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h +++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h @@ -51,14 +51,21 @@ extern void unbind_virq_from_irq(int virq); extern int bind_ipi_to_irq(int ipi); extern void unbind_ipi_from_irq(int ipi); -/* Dynamically bind an event-channel port to Linux IRQ space. */ +/* + * Dynamically bind an event-channel port to Linux IRQ space. + * BIND: Returns IRQ or error. + * UNBIND: Takes IRQ to unbind from; automatically closes the event channel. + */ extern int bind_evtchn_to_irq(unsigned int evtchn); -extern void unbind_evtchn_from_irq(unsigned int evtchn); +extern void unbind_evtchn_from_irq(unsigned int irq); /* * Dynamically bind an event-channel port to an IRQ-like callback handler. * On some platforms this may not be implemented via the Linux IRQ subsystem. - * You *cannot* trust the irq argument passed to the callback handler. + * The IRQ argument passed to the callback handler is the same as returned + * from the bind call. It may not correspond to a Linux IRQ number. + * BIND: Returns IRQ or error. + * UNBIND: Takes IRQ to unbind from; automatically closes the event channel. */ extern int bind_evtchn_to_irqhandler( unsigned int evtchn, @@ -66,7 +73,7 @@ extern int bind_evtchn_to_irqhandler( unsigned long irqflags, const char *devname, void *dev_id); -extern void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id); +extern void unbind_evtchn_from_irqhandler(unsigned int irq, void *dev_id); extern void irq_resume(void);